#include "calculatornumber.h"
  
  
  
CalculatorNumber :: CalculatorNumber()
{
  clearData();
}

void CalculatorNumber :: operator=(CalculatorNumber &otherNumber)
{
  longLongData_=otherNumber.getLongLongData();
  doubleData_=otherNumber.getDoubleData();
  isDouble_=otherNumber.isDouble();
}

void CalculatorNumber :: setDouble(double doubleData)
{
  doubleData_ = doubleData;
  isDouble_=true;
}
 
void CalculatorNumber :: setLongLong(long long longLongData)
{
  longLongData_ = longLongData;
  isDouble_=false;
}


double CalculatorNumber :: getDoubleData()
{
  return doubleData_;
}

long long CalculatorNumber :: getLongLongData()
{
  return longLongData_;
}


/*This function uses string streams to convert the data into a string.*/
string CalculatorNumber :: getData()
{
  string tempString;
  ostringstream conversionStream;
  tempString.clear();
  int i, j;
  bool carry;
  
  

  

  /*If the CalculatorNumber is a double...*/
  if(isDouble_)
  {
    /*Could make representation type and precision flexible.*/
    conversionStream << setprecision(15) << fixed << doubleData_;
    tempString=conversionStream.str();

/*Force length to be <= 15 digits, because IEEE double precision floating point
is accurate up to that point.*/
    for(i=tempString.length()-1; i>15; i--)
    {
/*Was trying to prevent floating point error by implementing a rounding
function, however it doesn't work. This can be fixed later.*/
   /*   if(tempString[i]>=5)
      {
        carry=true;
        for(j=tempString.length()-2; j>0; j--)
        {
          if(!carry)
            break;
          if('.'!=tempString[j] && '-'!=tempString[j])
          {
            if('9'<=tempString[j])
            {
              tempString[j]++;
              carry=false;
            }
          }
        }
        if(carry)
        {
          if(tempString[0]=='-')
            tempString.insert(1, "1");
          else
            tempString.insert(0, "1");
        }
      }*/
      tempString.erase(tempString.length()-1); 
    }

/*Remove trailing zeroes, and if all decimal digits are consumed convert back
into a long long.*/
    for(i=tempString.length()-1; i>0; i--)
    {
      if(tempString[i]=='.')
      {
        sscanf(tempString.c_str(), "%lld", &longLongData_);
        tempString.erase(i);
        isDouble_=false;
        return tempString;
      }
      if(tempString[i]=='0')
        tempString.erase(i);
      else
        return tempString;
    }
  } //end if

  /*If the CalculatorNumber is a long long...*/
  conversionStream << longLongData_;
  return conversionStream.str();
}

/*Basically, calling this with (true) tells the CalculatorNumber to use its
doubleData_ member, and calling this with false tells the CalculatorNumber to 
use its longLongData_ member.*/ 
void CalculatorNumber :: setToDouble(bool x)
{

  if(x!=isDouble_)
    isDouble_=!isDouble_;
}

bool CalculatorNumber :: isDouble()
{
  if(isDouble_)
    return true;
  return false;
}



/*The add, sub, mul, and div functions basically get the data of num1 and num2
and sets the value of the current CalculatorNumber to the result. If either of
the two arguments are doubles, then the result is made into a double, otherwise
it is made into a long long. The reason string streams are used is because the
method getData() returns a string (because the value inside of the 
CalculatorNumber can be a double or a long long)*/

void CalculatorNumber :: add(CalculatorNumber *num1, CalculatorNumber *num2)
{
  stringstream tmpstream;
  double tmp;
  long long tmp2;

  tmpstream << num1->getData() << " " << num2->getData();

  if(num1->isDouble() || num2->isDouble())
  {
    isDouble_=true;
    tmpstream >> doubleData_ >> tmp;
    doubleData_+=tmp;
  }
  else
  {
    isDouble_=false;
    tmpstream >> longLongData_ >> tmp2;
    longLongData_+=tmp2;
  }
}

void CalculatorNumber :: sub(CalculatorNumber *num1, CalculatorNumber *num2)
{
  stringstream tmpstream;
  double tmp;
  long long tmp2;

  tmpstream << num1->getData() << " " << num2->getData();

  if(num1->isDouble() || num2->isDouble())
  {
    isDouble_=true;
    tmpstream >> doubleData_ >> tmp;
    doubleData_-=tmp;
  }
  else
  {
    isDouble_=false;
    tmpstream >> longLongData_ >> tmp2;
    longLongData_-=tmp2;
  }
}

void CalculatorNumber :: mul(CalculatorNumber *num1, CalculatorNumber *num2)
{
  stringstream tmpstream;
  double tmp;
  long long tmp2;

  tmpstream << num1->getData() << " " << num2->getData();

  if(num1->isDouble() || num2->isDouble())
  {
    isDouble_=true;
    tmpstream >> doubleData_ >> tmp;
    doubleData_*=tmp;
  }
  else
  {
    isDouble_=false;
    tmpstream >> longLongData_ >> tmp2;
    longLongData_*=tmp2;
  }
}


void CalculatorNumber :: div(CalculatorNumber *num1, CalculatorNumber *num2)
{
  stringstream tmpstream;
  double dtmp1, dtmp2;
  long long tmp1, tmp2;
  
  
  tmpstream << num1->getData() << " " << num2->getData();

/*Recall the numbers as correct data type.*/
  if(num1->isDouble() || num2->isDouble())
    tmpstream >> dtmp1 >> dtmp2;
  else
    tmpstream >> tmp1 >> tmp2;

/*This block checks to see if integer division is okay.*/
  if(!(num1->isDouble() || num2->isDouble()))
  {
    if(0==tmp1%tmp2)
    {
      if(tmp2==0)
      {
        longLongData_=0;
        return;
      }
      longLongData_=tmp1/tmp2;
      return;
    }
/*If integer division is not okay...*/
    isDouble_=true;
    doubleData_=(double)tmp1/(double)tmp2;
    return;
  }


/*Handles division with doubles.*/
  isDouble_=true;
  if(dtmp2==0.0)
  {
    doubleData_=0.0;
    return;
  }
  doubleData_=dtmp1/dtmp2;
}

void CalculatorNumber :: clearData()
{
  isDouble_=false;
  longLongData_=0;
  doubleData_=0.0;
}


